//! 加密/哈希工具

use sha2::{Sha256, Digest};
use sha3::Sha3_256;
use md5;
use uuid::Uuid;
use rand::{Rng, thread_rng};
use rand::distributions::Alphanumeric;

/// 计算字符串的SHA256哈希值
/// 
/// # 示例
/// 
/// ```
/// use rust_utils::crypto_utils::sha256;
/// 
/// let hash = sha256("hello world");
/// assert_eq!(hash.len(), 64); // SHA256 produces 64-character hex string
/// ```
pub fn sha256(input: &str) -> String {
    let mut hasher = Sha256::new();
    hasher.update(input.as_bytes());
    let result = hasher.finalize();
    format!("{:x}", result)
}

/// 计算字符串的SHA3-256哈希值
/// 
/// # 示例
/// 
/// ```
/// use rust_utils::crypto_utils::sha3_256;
/// 
/// let hash = sha3_256("hello world");
/// assert_eq!(hash.len(), 64); // SHA3-256 produces 64-character hex string
/// ```
pub fn sha3_256(input: &str) -> String {
    let mut hasher = Sha3_256::new();
    hasher.update(input.as_bytes());
    let result = hasher.finalize();
    format!("{:x}", result)
}

/// 计算字符串的MD5哈希值
/// 
/// # 示例
/// 
/// ```
/// use rust_utils::crypto_utils::md5_hash;
/// 
/// let hash = md5_hash("hello world");
/// assert_eq!(hash.len(), 32); // MD5 produces 32-character hex string
/// ```
pub fn md5_hash(input: &str) -> String {
    format!("{:x}", md5::compute(input))
}

/// 生成UUID v4
/// 
/// # 示例
/// 
/// ```
/// use rust_utils::crypto_utils::generate_uuid;
/// 
/// let uuid = generate_uuid();
/// assert_eq!(uuid.len(), 36); // UUID v4 has 36 characters including hyphens
/// ```
pub fn generate_uuid() -> String {
    Uuid::new_v4().to_string()
}

/// 生成随机字符串
/// 
/// # 示例
/// 
/// ```
/// use rust_utils::crypto_utils::random_string;
/// 
/// let random_str = random_string(10);
/// assert_eq!(random_str.len(), 10);
/// ```
pub fn random_string(len: usize) -> String {
    thread_rng()
        .sample_iter(&Alphanumeric)
        .take(len)
        .map(char::from)
        .collect()
}

/// 生成指定范围内的随机数
/// 
/// # 示例
/// 
/// ```
/// use rust_utils::crypto_utils::random_number;
/// 
/// let num = random_number(1, 100);
/// assert!(num >= 1 && num < 100);
/// ```
pub fn random_number(min: i32, max: i32) -> i32 {
    thread_rng().gen_range(min..max)
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_sha256() {
        let hash = sha256("hello world");
        assert_eq!(hash.len(), 64);
        assert_eq!(
            hash,
            "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"
        );
    }

    #[test]
    fn test_sha3_256() {
        let hash = sha3_256("hello world");
        assert_eq!(hash.len(), 64);
    }

    #[test]
    fn test_md5_hash() {
        let hash = md5_hash("hello world");
        assert_eq!(hash.len(), 32);
        assert_eq!(hash, "5eb63bbbe01eeed093cb22bb8f5acdc3");
    }

    #[test]
    fn test_generate_uuid() {
        let uuid = generate_uuid();
        assert_eq!(uuid.len(), 36);
        // Check if it's a valid UUID format
        assert!(uuid.chars().all(|c| c.is_ascii_hexdigit() || c == '-'));
    }

    #[test]
    fn test_random_string() {
        let random_str = random_string(10);
        assert_eq!(random_str.len(), 10);
        // Check if all characters are alphanumeric
        assert!(random_str.chars().all(|c| c.is_ascii_alphanumeric()));
    }

    #[test]
    fn test_random_number() {
        let num = random_number(1, 100);
        assert!(num >= 1 && num < 100);
    }
}